package de.gameduell.framework.game {
	import de.gameduell.framework.debug.Debug;
	import de.gameduell.framework.locale.LocaleTools;
	
	import flash.display.Bitmap;
	import flash.display.Loader;
	import flash.display.PixelSnapping;
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IOErrorEvent;
	import flash.net.URLRequest;
	import flash.system.ApplicationDomain;
	import flash.system.LoaderContext;		

	/**
	 * Class Player
	 * GameDuell default player. Provides standard functionality
	 * e.g. getter / setter for name and avatar, rank, etc.
	 */
	public class Player extends EventDispatcher{
		
		public static const ACTIVE_CHANGE:String = "ACTIVE_CHANGE";
		public static const LEFT_GAME:String     = "PLAYER_LEFT";
		public static const POINTS_CHANGE:String = "POINTS_CHANGE";
		public static const AVATAR:String 		 = "AVATAR";
		public static const NO_RANK:String	     = "-";
		
		private const MAX_CHARS:Number	 = 10;
		private const SHORT_CHARS:Number = 8;
		private const SHORTY_END:String	 = "..";
	
		private var _name:String;
		private var _avatar:String;
		private var _shortName:String;
		private var _rank:String;
		private var _active:Boolean;
		private var _points:Number;
		private var _type:String;
		private var _identity:Number;
		private var _isUser:Boolean;
		private var _isKI:Boolean;
		private var _avatarBitmap:Bitmap;

		/**
		 * Class constructor
		 */
		public function Player(name:String, aAvatar:String, rank:String = NO_RANK, isComputer:Boolean = false){
			_avatarBitmap = new Bitmap();
			avatar 	      = aAvatar;

			_name   	= name;
			_points 	= 0;
			_shortName	= buildShortName();
			_rank		= rank;
			_active		= false;
			
			_isKI = isComputer;
		}
		
		// ################### setter functions ######################################################
		
		/**
		 * sets player's state to active/inactive
		 * @param state new player state
		 */
		public function set active( state:Boolean ):void{		
			if(_active != state){
				_active = state;
				dispatchEvent(new Event(ACTIVE_CHANGE));
			}	
			_active = state;
		}
		
		/**
		 * sets player's type like "black" and "white" 
		 * or something else 
		 * 
		 * @param aType	the new type of the player
		 */
		public function set type(aType:String):void{
			_type = aType;
		}
		
		/**
		 * for example the index in the controller array
		 * 
		 * @param aIdentity	the identity of the player
		 */
		public function set identity(aIdentity:Number):void{
			_identity = aIdentity;
		}
		
		/**
		 * sets player's points (if your game don't need points
		 * then just ignore this)
		 * 
		 * @param aPoints the new points of the player
		 */
		public function set points(aPoints:Number):void{
			_points = aPoints;
			dispatchEvent(new Event(POINTS_CHANGE));
		}
		
		/**
		 * set new name for player
		 * @param name	new name for player
		 */
		public function set name( name:String ):void{
			_name = name;
		}
		
		/**
		 * set user's short name manually
		 * @param shorty - short user name
		 */
		public function set shortName( shorty:String ):void{
			_shortName = shorty;
		}
		
		/**
		 * set new avatar for player
		 * @param avatar  new avatar for player
		 */
		public function set avatar(avatarUrl:String):void{
			_avatar = avatarUrl;
			
			if(_avatar != "null" && _avatar != "" && LocaleTools.isURL(_avatar)){
				var aContext:LoaderContext = new LoaderContext(true, ApplicationDomain.currentDomain);
				var loader:Loader = new Loader();
	            loader.contentLoaderInfo.addEventListener(Event.COMPLETE, avatarLoaded);
	            loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, ioErrorHandler);
	            var request:URLRequest = new URLRequest(_avatar);
				try{
					loader.load(request, aContext);
				}catch(e:Error){
					Debug.trace("Player::setAvatar: error while loading avatar image", Debug.WARNING);
				}
			}
		}

		private function avatarLoaded(event:Event):void {
			try {	
				var loader:Loader = Loader(event.target["loader"]);
				_avatarBitmap     = Bitmap(loader.content);
				_avatarBitmap.smoothing = true;
				_avatarBitmap.pixelSnapping = PixelSnapping.NEVER;
			}catch(error:Error) {
				Debug.trace("Player::avatarLoaded: error while loading avatar image" + ":" + error.getStackTrace(), Debug.WARNING);
			}
			dispatchEvent(new Event(AVATAR));
		}

		private function ioErrorHandler(event:Event):void {
		
		}

		public function set isUser(user:Boolean):void{
			 _isUser = user;
		}

		public function set isKI(ki:Boolean):void{
			 _isKI = ki;
		}
		
		// ################### getter functions ###########################################################
		
		public function get points():Number{
			return _points;
		}
		
		/** @return players type */
		public function get type():String {
			return _type;
		}
		
		/** @return players state */
		public function get active():Boolean {
			return _active;
		}
		
		/** @return player's name */
		public function get name():String {
			return _name;
		}
		
		/** @return player's avatar */
		public function get avatarUrl():String {
			return _avatar;
		}
		
		public function get avatarBitmap():Bitmap {
//			return _avatarBitmap;
			return new Bitmap(_avatarBitmap.bitmapData,_avatarBitmap.pixelSnapping,_avatarBitmap.smoothing);
		}
		
  		public function get avatarSprite():Sprite {
   			var pic:Sprite = new Sprite();
   			pic.addChild(avatarBitmap);
   			return pic;
  		}
  				
		/** @return player's short name */
		public function get shortName():String {
			return _shortName;
		}
		
		/**
		 * for example the index in the controller array
		 * 
		 * @return the identity of the player
		 */
		public function get identity():Number{
			return _identity;
		}
		
		public function get isUser():Boolean{
			return _isUser;
		}
		
		/**
		 * returns true if the player is controlled by the server and not a real user
		 */
		public function get isKI():Boolean{
			return _isKI;
		}
	
		// ################### misc functions ###############################################################
		
		/**
		 * Truncate usernames which are longer then MAX_CHARS down to SHORT_CHARS
		 * 
		 * @param name the long version of the name
		 * 
		 * @return short user name 
		 */
		private function buildShortName():String {
			var shorty:String = _name;
			if( name.length > MAX_CHARS){
				shorty = shorty.substring(0,SHORT_CHARS-1) + SHORTY_END;
			}
			return shorty;
		} 
		
		public function leftGame():void{
			dispatchEvent(new Event(LEFT_GAME));
		}
	}
}
